import { Thread } from '../models/Thread';
import { Action } from 'redux';
import * as ThreadActions from '../actions/thread-actions';
import { Message } from '../models/message';

export interface ThreadsEntities {
    [id: string]: Thread;
}

export interface ThreadsState {
    ids: string[];
    entities: ThreadsEntities;
    currentThreadId?: string;
}

const initialThreadState: ThreadsState = {
    ids: [],
    entities: {},
    currentThreadId: null
};

export const ThreadsReducer = function (state: ThreadsState = initialThreadState, action: Action): ThreadsState {
    switch (action.type) {
        case ThreadActions.ADD_THREAD: {
            const thread = (<ThreadActions.AddThreadAction>action).thread;
            if (state.ids.includes(thread.id)) {
                return state;
            }
            return {
                ids: [...state.ids, thread.id],
                currentThreadId: state.currentThreadId,
                entities: Object.assign(state.entities, { [thread.id]: thread })
            };
        }
        case ThreadActions.ADD_MESSAGE: {
            const thread = (<ThreadActions.AddMessageAction>action).thread;
            const message = (<ThreadActions.AddMessageAction>action).message;
            const isRead = message.thread.id === state.currentThreadId ? true : message.isRead;
            const newMessage = Object.assign({}, message, isRead);
            const oldThread = state.entities[thread.id];
            const newThread = Object.assign({}, oldThread, { message: [...oldThread.messages, newMessage] });
            return {
                ids: state.ids,
                entities: Object.assign({}, state.entities, { [thread.id]: newThread }),
                currentThreadId: state.currentThreadId
            };
        }
        case ThreadActions.SELECT_THREAD: {
            const thread = (<ThreadActions.SelectThreadAction>action).thread;
            const oldThread = state.entities[thread.id];
            const newMessages = oldThread.messages
                .map((message) => Object.assign({}, message, { isRead: true }));
            const newThread = Object.assign({}, thread, { messages: newMessages });
            return {
                ids: state.ids,
                currentThreadId: thread.id,
                entities: Object.assign({}, state.entities, { [newThread.id]: newThread })
            };
        }
        default:
            return state;
    }
};
